Skip to content

🐛 llx: stop array contains/difference builtins panicking on a null argument#8320

Merged
tas50 merged 2 commits into
mainfrom
worktree-fix-pam-containsall-panic
Jun 13, 2026
Merged

🐛 llx: stop array contains/difference builtins panicking on a null argument#8320
tas50 merged 2 commits into
mainfrom
worktree-fix-pam-containsall-panic

Conversation

@tas50

@tas50 tas50 commented Jun 10, 2026

Copy link
Copy Markdown
Member

Fixes #8319

Problem

A surge of client scan panics (panic: interface conversion: interface {} is nil, not []interface {}) traced to the array contains*/difference builtins.

arrayContainsAll, arrayContainsNone, and arrayDifferenceV2 guard the receiver array against null but then perform an unchecked arg.Value.([]any) on the argument. When the argument resolves to a typed null array — e.g. a map[string][]T key miss like pam.conf.services["su"] on hosts with no /etc/pam.d (container-optimized k8s node OSes: COS, Flatcar, Bottlerocket) — that type assertion panics.

Because the MQL executor runs blocks in goroutines, the panic is unrecoverable by the caller and crashes the entire scan rather than failing the single check. The dict variants (dictContainsAll/dictContainsNone) already use the safe comma-ok form, so only the array variants were affected.

Fix

Guard the argument the same way the receiver is already guarded: a null argument propagates as null (placed before the type check so an untyped null short-circuits cleanly too). The compiled … == [] wrapper then resolves the check to a clean pass/fail.

After the fix, realArray.containsAll(nullArg) returns null → the check resolves to false (fails cleanly) instead of crashing. Whether a pam-absent host should pass or fail the check remains a policy decision; the engine's responsibility here is simply to not panic.

Testing

  • Reproduced the exact panic with a = {a: [1,2]}; [1,2,3].containsAll(a['b']) (typed-null arg via map key miss); confirmed crash pre-fix, clean result post-fix.
  • Added regression cases for containsAll / containsNone / difference to TestArray.
  • go test ./llx/ and the full ./providers/core/resources/ suite pass.

@mondoo-code-review mondoo-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes scan crashes when array builtins (containsAll, containsNone, difference) receive a null argument

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Test Results

9 872 tests  +4   9 866 ✅ +4   4m 52s ⏱️ + 1m 41s
  543 suites ±0       6 💤 ±0 
   40 files   ±0       0 ❌ ±0 

Results for commit bef0ef7. ± Comparison against base commit 1e52755.

♻️ This comment has been updated with latest results.

@jaym

jaym commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #8319

tas50 and others added 2 commits June 13, 2026 12:35
…gument

`arrayContainsAll`, `arrayContainsNone`, and `arrayDifferenceV2` guarded the
receiver array against null but then did an unchecked `arg.Value.([]any)` on
the argument. When the argument resolves to a typed null array — e.g. a
`map[string][]T` key miss such as `pam.conf.services["su"]` on a host with no
`/etc/pam.d` (COS, Flatcar, Bottlerocket k8s nodes) — that assertion panics
with `interface conversion: interface {} is nil, not []interface {}`.

Because the executor runs blocks in goroutines the panic is unrecoverable and
crashes the entire scan rather than failing the single check. The dict
variants already use the safe comma-ok form; only the array variants were
affected.

Guard the argument the same way the receiver is guarded: a null argument
propagates as null. The compiled `… == []` wrapper then resolves the check to
a clean pass/fail instead of crashing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mondoo-linux-security's su-restriction check relies on
`groups.containsAll(suRestrictedGroups)` being true when suRestrictedGroups is
an empty (typed, non-null) []string. Add a regression test pinning that
containsAll of an empty list is vacuously satisfied, distinct from the null-arg
case which propagates null.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tas50 tas50 force-pushed the worktree-fix-pam-containsall-panic branch from bef0ef7 to cd61a88 Compare June 13, 2026 19:35
@tas50 tas50 merged commit e96c40c into main Jun 13, 2026
22 checks passed
@tas50 tas50 deleted the worktree-fix-pam-containsall-panic branch June 13, 2026 19:58
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

panic in llx.arrayContainsAll when containsAll argument evaluates to null (interface conversion: interface {} is nil)

2 participants